﻿Option Explicit On

Imports System.Xml
Imports System.IO
Imports System.Security.Permissions
Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
Imports System.Security.Cryptography.Xml

Public Class frmFerramentasAssinaturaLote

    Private Sub frmFerramentasAssinaturaLote_Load(sender As Object, e As System.EventArgs) Handles Me.Load
        Call MontaGrid()
    End Sub

    Private Sub MontaGrid()
        Try
            '-- DataGridView
            With dgvArquivos
                .SelectionMode = DataGridViewSelectionMode.FullRowSelect
                .AllowUserToAddRows = False
                .AllowUserToDeleteRows = False
                .AllowUserToResizeRows = False
                '.AlternatingRowsDefaultCellStyle.BackColor = Color.DarkGray'-- zebrado
                .ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
                .MultiSelect = False
                .ConnectionString = strMyDBString
                .SQL = ""
                .AddColumn("#", 0, True)
                .AddColumn("Arquivo", 0, True)
                .AddColumn("Tipo", 150)
                .AddColumn("Situação", 150)
                .AddColumn("OBS", 150)
                .FillColumns() '-- Monta colunas quando grid é preenchido manualmente
            End With
        Catch ex As Exception
            Call SendError(ex.Message, ex.StackTrace)
        End Try
    End Sub
    ''' <summary>
    ''' Abre documento XML e valida-o
    ''' </summary>
    ''' <remarks>3.4.3.26</remarks>
    Private Sub AbrirXML(Optional ByVal strFileName As String = "")
        Dim strAssinatura As String = ""
        Dim strDocumento As String = ""
        Dim strOBS As String = ""
        Dim myColor As Color = Color.LemonChiffon
        Call Application.DoEvents()
        Try
            Dim strValElement As String = ""
            Dim strXML As String = ""
            Dim MyXml As New XmlDocument()
            Dim myFileName As OpenFileDialog = New OpenFileDialog()
            If IsEmpty(strFileName) Then
                With myFileName
                    .Title = "Arquivos XML"
                    .Filter = "Arquivos XML (*.xml)|*.xml"
                    .ShowDialog()
                    strFileName = .FileName
                End With
            End If
            If Trim(strFileName) = "" Then Exit Sub
            With MyXml
                '.PreserveWhitespace = False
                .Load(strFileName)
                '-- mostrando conteudo
                'txtXML.Text = .OuterXml
                If .FirstChild.Name = "xml" Then
                    strXML = .GetElementsByTagName(.FirstChild.NextSibling.Name.ToString).Item(0).OuterXml
                    .LoadXml(strXML)
                End If
                '-- RETORNOS
                Select Case .FirstChild.Name
                    Case "retEnviNFe"
                        strDocumento = "Recibo de Envio de Lote"
                        Exit Sub
                    Case "retConsReciNFe "
                        strDocumento = "Recibo de Processamento de Lote"
                        Exit Sub
                    Case "retCancNFe "
                        strDocumento = "Retorno da Solicitação de Cancelamento"
                        Exit Sub
                    Case "retInutNFe "
                        strDocumento = "Retorno da Solicitação de Inutilização"
                    Case "retConsSitNFe"
                        strDocumento = "Retorno de Consulta de Situação"
                        Exit Sub
                    Case "retConsStatServ"
                        strDocumento = "Retorno de Consulta do Status do Serviço"
                        Exit Sub
                    Case "retConsCad"
                        strDocumento = "Retorno de Consulta de Cadastro"
                        Exit Sub
                    Case "nfeProc"
                        strDocumento = "Protocolo de autorização"
                        strValElement = "NFe"
                    Case "NFe", "infNFe"
                        strDocumento = "Dados da NFe"
                        strValElement = "NFe"
                    Case "enviNFe"
                        strDocumento = "Envio de Lote da NFe"
                        strValElement = "NFe"
                    Case "cancNFe"
                        strDocumento = "Cancelamento de NFe"
                        strValElement = "cancNFe"
                    Case "procCancNFe"
                        strDocumento = "Protocolo de Cancelamento de NFe"
                        strValElement = "cancNFe"
                    Case "inutNFe"
                        strDocumento = "Inutilização de Numeração de NFe"
                        strValElement = "inutNFe"
                    Case "procInutNFe"
                        strDocumento = "Protocolo de Inutilização de Numeração de NFe"
                        strValElement = "inutNFe"
                    Case "conSitNFe", "consSitNFe"
                        strDocumento = "Consulta de Situação da NFe"
                        Exit Sub
                    Case "consStatServ"
                        strDocumento = "Consulta de Status do Serviço"
                        Exit Sub
                    Case "consCad"
                        strDocumento = "Consulta de Cadastro de Contribuintes"
                        Exit Sub
                    Case Else
                        strDocumento = "Documento desconhecido"
                        Exit Sub
                End Select
            End With
            If ValidarAssinaturaDigNFe(strFileName, strValElement) = True Then
                strAssinatura = "Assinatura válida!"
                myColor = Color.LightGreen
            Else
                strAssinatura = "Assinatura inválida!"
                myColor = Color.Bisque
            End If
        Catch ex As Exception
            'Call SendError(ex.Message, ex.StackTrace)
            strOBS = ex.Message
            myColor = Color.Red
        End Try

        With dgvArquivos
            .Rows.Add()
            .TextMatrix(.RowCount - 1, 0) = .RowCount
            .TextMatrix(.RowCount - 1, 1) = strFileName
            .TextMatrix(.RowCount - 1, 2) = strDocumento
            .TextMatrix(.RowCount - 1, 3) = strAssinatura
            .TextMatrix(.RowCount - 1, 4) = strOBS
            .LineColor(.RowCount - 1, myColor)

            stBar.Value = .RowCount
        End With

    End Sub
    ''' <summary>
    ''' Validador de assinatura digital para NFe e afins
    ''' </summary>
    ''' <param name="FilePath">Caminho do arquivo XML</param>
    ''' <param name="strElement">Nome do elemento assinado</param>
    ''' <returns></returns>
    ''' <remarks>Functional</remarks>
    Public Function ValidarAssinaturaDigNFe(ByVal FilePath As String, Optional ByVal strElement As String = "NFe") As Boolean
        Try
            '-- carregar o XML da NF-e
            Dim xml As New XmlDocument()
            xml.PreserveWhitespace = True
            xml.Load(FilePath)

            If xml.GetElementsByTagName(strElement).Count > 0 Then
                Return CheckSignatureNFe(xml.GetElementsByTagName(strElement))
            Else
                Return False
            End If
        Catch ex As Exception
            Call MsgBox(ex.Message, MsgBoxStyle.Critical)
            Return False
        End Try
    End Function
    ''' <summary>
    ''' Verifica se tem assinatura e se está correta
    ''' </summary>
    ''' <param name="tagVal">Tag assinada</param>
    ''' <returns></returns>
    ''' <remarks>3.4.3.26</remarks>
    Private Function CheckSignatureNFe(ByVal tagVal As XmlNodeList) As Boolean
        Try
            '-- pegar a Tag "NFe", à que contem assinatura dig.
            Dim nodeNFe As XmlNodeList = tagVal
            Dim NFe As String = nodeNFe(0).OuterXml.ToString

            '--carregar o XML da NFe 
            Dim xmlNFe As New XmlDocument()
            xmlNFe.PreserveWhitespace = True
            xmlNFe.LoadXml(NFe)

            '--Carregar a assinatura
            Dim signedXml As New SignedXml(xmlNFe)
            Dim nodeList As XmlNodeList = xmlNFe.GetElementsByTagName("Signature")
            signedXml.LoadXml(nodeList(0))

            '--buscar o KeyInfo da assinatura
            Dim keyInfoItems As IEnumerator = signedXml.KeyInfo.GetEnumerator()
            keyInfoItems.MoveNext()
            Dim keyInfoX509 As KeyInfoX509Data = keyInfoItems.Current() '(KeyInfoX509Data)keyInfoItems.Current

            '--buscar o certificado do KeyInfo
            Dim keyInfoCert As X509Certificate2 = keyInfoX509.Certificates(0)

            '--Validar se assinatura é valida
            Return signedXml.CheckSignature(keyInfoCert.PublicKey.Key)
        Catch ex As Exception
            Return False
        End Try
    End Function

    Private Sub dgvArquivos_CellDoubleClick(sender As Object, e As System.Windows.Forms.DataGridViewCellEventArgs)

    End Sub

    Private Sub dgvArquivos_DragDrop(sender As Object, e As System.Windows.Forms.DragEventArgs) Handles dgvArquivos.DragDrop
        If e.Data.GetDataPresent("FileDrop") Then
            '-- limpando
            dgvArquivos.Clear()

            Dim files As String() = TryCast(e.Data.GetData("FileDrop"), String())
            stBar.Maximum = files.GetLength(0)
            For Each file As String In files
                lblStatus.Text = "Validando: " & file.ToString
                Call AbrirXML(file.ToString)
            Next
            lblStatus.Text = "..."
        End If
    End Sub

    Private Sub dgvArquivos_DragEnter(sender As Object, e As System.Windows.Forms.DragEventArgs) Handles dgvArquivos.DragEnter
        e.Effect = DragDropEffects.Move
    End Sub
End Class